#include "mphandle.h"
#include "mpconfig.h"
#include "mputils.h"
#include "CTNull.h"

bool CMpHandle::s_bExit = false;
bool CMpHandle::s_bReloadConfig = false;

CMpHandle::CMpHandle():
    m_stSocket(PF_LOCAL, SOCK_STREAM, true)
{
}

CMpHandle::~CMpHandle()
{
}

void CMpHandle::Init()
{
    CT_TRACE(("begin init handle"));
    int iRet = 0;

    //安装信号处理函数
    signal(SIGUSR1, CMpHandle::sigusr1_handle);	// kill -USR1 pid 会让程序重读配置
    signal(SIGUSR2, CMpHandle::sigusr2_handle);	// kill -USR2 pid 会让程序安全的退出

    // 连接到MpNet
    iRet = m_stSocket.Connect(CONF->ProcessSocket);
    CHECK_THROW(iRet);

    // 初始化缓冲区
    iRet = m_stRecvBuffer.Attach(NULL, CONF->ProcessRecvSize, 0);
    CHECK_THROW(iRet);

    iRet = m_stSendBuffer.Attach(NULL, CONF->ProcessSendSize, 0);
    CHECK_THROW(iRet);

	iRet = m_stSoLoader.LoadSoApp(CONF->SoFile);
	CHECK_THROW(iRet);

	m_pstSoApp = m_stSoLoader.CreateSoApp();
	iRet = m_pstSoApp->Init(CONF->SoConfigFile);
	CHECK_THROW(iRet);
}

void CMpHandle::Run()
{
    int iRet = 0;
    char* pszCode = NULL;
    int iCodeLen = 0;

    while (true)
    {
        // 信号检查
        if (s_bReloadConfig)
        {
            s_bReloadConfig = false;
            ReloadConfig();
        }

        if (s_bExit)
        {
            s_bExit = false;
            return;
        }

        Send();

        // 接收数据
        iRet = RecvOneCode(pszCode, iCodeLen);
        if (iRet != 0)
        {
            if (iRet == CMpUtils::RET_RECV_ZERO_MSG) //收到长度为0的包
            {
                CT_TRACE(("recv length = 0"));
                while(m_stSendBuffer.GetUsedLen() != 0)
                {
                    Send();
                }
            }
            m_stSocket.Close();
            CT_TRACE(("close connect"));
            s_bExit = true;
            return;
        }

        if (iCodeLen == 0)
        {
            continue;
        }

        // 处理
        // 先空出4字节 用来存放长度
        char* pszAnsLen = m_stSendBuffer.GetFreeBuf();
        m_stSendBuffer.Append(sizeof(int));

        int iAnsLen = 0;
		iRet = m_pstSoApp->Do(pszCode, iCodeLen, m_stSendBuffer.GetFreeBuf(),
			m_stSendBuffer.GetFreeLen(), iAnsLen);

        // 把接收到并已经处理的数据删掉
        m_stRecvBuffer.Remove(iCodeLen);
        m_stSendBuffer.Append(iAnsLen);

        // 把长度填到头部
        *(int*)pszAnsLen = htonl(iAnsLen);

        CT_TRACE(("handle's ans has %d bytes", iAnsLen));

        // 下发数据
        Send();
    }
}

void CMpHandle::Exit()
{
    CT_TRACE(("mphandle(%d) exit", getpid()));

	m_pstSoApp->Exit();
	m_stSoLoader.DestroySoApp(m_pstSoApp);
}

void CMpHandle::sigusr1_handle(int CT_UNUSED(iSigVal))
{
    s_bReloadConfig = true;
    signal(SIGUSR1, CMpHandle::sigusr1_handle);
}

void CMpHandle::sigusr2_handle(int CT_UNUSED(iSigVal))
{
    s_bExit = true;
    signal(SIGUSR2, CMpHandle::sigusr2_handle);
}

void CMpHandle::ReloadConfig()
{
}

int CMpHandle::RecvOneCode(char*& pszCodeBuf, int& iCodeLen)
{
    int iRet = CMpUtils::RecvOneCode(m_stSocket, m_stRecvBuffer, pszCodeBuf, iCodeLen);
    if (iRet)
    {
		if (iRet == CT_EINPROGRESS || iRet == CT_EWOULDBLOCK || iRet == CT_ETIME)
		{
			return 0;
		}
		else if (iRet == CMpUtils::RET_RECV_ZERO_MSG) // 收到0字节的消息, 被要求退出
		{
			CT_TRACE(("recv 0 bytes msg, mean exit msg"));
			return iRet;
		}	    
		else
		{
			CT_ERROR(("CMpUtils::RecvOneCode failed %d", iRet));
			return iRet;
		}
    }

    // net进程退出时会返回CT_ECONNRESET
    // 没有消息而超时时会返回CT_ETIME

    return 0;
}

void CMpHandle::Send()
{
    if (m_stSendBuffer.GetUsedLen() == 0)
    {
        return;
    }

    // 如果没有发送完, 缓存后继续发送
    int iRet = 0;
    int iSendLen = 0;

    iRet = m_stSocket.Send(m_stSendBuffer.GetUsedBuf(),
                           m_stSendBuffer.GetUsedLen(),
                           iSendLen);
    CHECK_THROW(iRet);
    if (iSendLen != m_stSendBuffer.GetUsedLen())
    {
        CT_WARNING((""));
    }

    m_stSendBuffer.Remove(iSendLen);

    CT_TRACE(("handle send %d bytes to net, remain %d bytes",
        iSendLen, m_stSendBuffer.GetUsedLen()));
}
